<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Readme</title>
  <style>
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <link rel="stylesheet" href="../../../../../_htmresc/mini-st_2020.css" />
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="row">
<section id="nx_udp_echo_client-application-description" class="col-sm-12 col-lg-8">
<h2><b>Nx_UDP_Echo_Client application description</b></h2>
<p>This application provides an example of Azure RTOS NetXDuo stack usage. It shows how to develop a NetXDuo udp client to communicate with a remote sever using the NetXDuo UDP socket API.</p>
<p>The main entry function tx_application_define() is called by ThreadX during kernel start, at this stage, all NetXDuo resources are created.</p>
<ul>
<li>A NX_PACKET_POOL is allocated</li>
<li>A NX_IP instance using that pool is initialized</li>
<li>The ARP, ICMP and UDP protocols are enabled for the NX_IP instance</li>
<li>A DHCP client is created.</li>
</ul>
<p>The application then creates 2 threads with the same priorities:</p>
<ul>
<li><strong>AppMainThread</strong> (priority 10, PreemtionThreashold 10) : created with the TX_AUTO_START flag to start automatically.</li>
<li><strong>AppUDPThread</strong> (priority 10, PreemtionThreashold 10) : created with the TX_DONT_START flag to be started later.</li>
</ul>
<p>The <strong>AppMainThread</strong> starts and perform the following actions:</p>
<ul>
<li>starts the DHCP client<br />
</li>
<li>waits for the IP address resolution<br />
</li>
<li>resumes the <strong>AppUDPThread</strong></li>
</ul>
<p>The <strong>AppUDPThread</strong>, once started:</p>
<ul>
<li>creates a UDP socket<br />
</li>
<li>connects to the remote UDP server on the predefined port<br />
</li>
<li>On connection success, the UDP client sends a MAX_PACKET_COUNT messages to the server.<br />
</li>
<li>At each message sent, the UDP client reads the sever response and prints it on the Hyperterminal and the green led is toggled.</li>
</ul>
<h4 id="expected-success-behavior"><b>Expected success behavior</b></h4>
<ul>
<li>The board IP address is printed on the HyperTerminal</li>
<li>The response messages sent by the server are printed on the HyerTerminal</li>
<li>if the <a href="https://github.com/PavelBansky/EchoTool/releases/tag/v1.5.0.0">echotool</a> utility is used the message sent by the client are displayed on the PC console.</li>
<li>a summary message similar to the following is printed on the HyperTerminal and the green LED is toggling.</li>
</ul>
<pre><code> SUCCESS : 100 / 100 packets sent</code></pre>
<h4 id="error-behaviors"><b>Error behaviors</b></h4>
<ul>
<li>the Red LED is toggling to indicate any error that have occurred.</li>
<li>In case the message exchange is not completed a failure message is printed on the HyperTerminal showing the actual sent message compared to the expected ones.</li>
</ul>
<h4 id="assumptions-if-any"><b>Assumptions if any</b></h4>
<ul>
<li>The Application is using the DHCP to acquire IP address, thus a DHCP server should be reachable by the board in the LAN used to test the application.</li>
<li>The application is configuring the Ethernet IP with a static predefined <i>MAC Address</i>, make sure to change it in case multiple boards are connected on the same LAN to avoid any potential network traffic issues.</li>
<li>The MAC Address is defined in the <code>main.c</code></li>
</ul>
<pre><code>void MX_ETH_Init(void)
{

   /* USER CODE BEGIN ETH_Init 0 */

  /* USER CODE END ETH_Init 0 */

   static uint8_t MACAddr[6];

  /* USER CODE BEGIN ETH_Init 1 */

  /* USER CODE END ETH_Init 1 */
  heth.Instance = ETH;
  heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
  heth.Init.Speed = ETH_SPEED_100M;
  heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
  heth.Init.PhyAddress = LAN8742A_PHY_ADDRESS;
  MACAddr[0] = 0x00;
  MACAddr[1] = 0x80;
  MACAddr[2] = 0xE1;
  MACAddr[3] = 0x00;
  MACAddr[4] = 0x00;
  MACAddr[5] = 0x00;</code></pre>
<h4 id="known-limitations"><b>Known limitations</b></h4>
<p>None</p>
<h4 id="threadx-usage-hints"><b>ThreadX usage hints</b></h4>
<ul>
<li>ThreadX uses the Systick as time base, thus it is mandatory that the HAL uses a separate time base through the TIM IPs.</li>
<li>ThreadX is configured with 100 ticks/sec by default, this should be taken into account when using delays or timeouts at application. It is always possible to reconfigure it in the “tx_user.h”, the “TX_TIMER_TICKS_PER_SECOND” define,but this should be reflected in “tx_initialize_low_level.s” file too.</li>
<li>ThreadX is disabling all interrupts during kernel start-up to avoid any unexpected behavior, therefore all system related calls (HAL, BSP) should be done either at the beginning of the application or inside the thread entry functions.</li>
<li>ThreadX offers the “tx_application_define()” function, that is automatically called by the tx_kernel_enter() API. It is highly recommended to use it to create all applications ThreadX related resources (threads, semaphores, memory pools…) but it should not in any way contain a system API call (HAL or BSP).</li>
<li>Using dynamic memory allocation requires to apply some changes to the linker file. ThreadX needs to pass a pointer to the first free memory location in RAM to the tx_application_define() function, using the “first_unused_memory” argument. This require changes in the linker files to expose this memory location.
<ul>
<li>For EWARM add the following section into the .icf file:</li>
</ul>
<pre><code>place in RAM_region    { last section FREE_MEM };</code></pre>
<ul>
<li>For MDK-ARM:</li>
</ul>
<pre><code>either define the RW_IRAM1 region in the &quot;.sct&quot; file
or modify the line below in &quot;tx_low_level_initilize.s to match the memory region being used
    LDR r1, =|Image$$RW_IRAM1$$ZI$$Limit|</code></pre>
<ul>
<li>For STM32CubeIDE add the following section into the .ld file:</li>
</ul>
<pre><code>._threadx_heap :
  {
     . = ALIGN(8);
     __RAM_segment_used_end__ = .;
     . = . + 64K;
     . = ALIGN(8);
   } &gt;RAM_D1 AT&gt; RAM_D1</code></pre>
<pre><code>The simplest way to provide memory for ThreadX is to define a new section, see ._threadx_heap above.
In the example above the ThreadX heap size is set to 64KBytes.
The ._threadx_heap must be located between the .bss and the ._user_heap_stack sections in the linker script.  
Caution: Make sure that ThreadX does not need more than the provided heap memory (64KBytes in this example).  
Read more in STM32CubeIDE User Guide, chapter: &quot;Linker script&quot;.</code></pre>
<ul>
<li>The “tx_initialize_low_level.s” should be also modified to enable the “USE_DYNAMIC_MEMORY_ALLOCATION” flag.</li>
</ul></li>
</ul>
<h3 id="keywords"><b>Keywords</b></h3>
<p>RTOS, Network, ThreadX, NetXDuo, TCP, UART</p>
<h3 id="hardware-and-software-environment"><b>Hardware and Software environment</b></h3>
<ul>
<li><p>This application runs on STM32F429xx devices</p></li>
<li><p>This application has been tested with STMicroelectronics STM32F429ZI Nucleo boards Revision MB1137 B-01 and can be easily tailored to any other supported device and development board.</p></li>
<li><p>This application uses USART3 to display logs, the hyperterminal configuration is as follows:</p>
<ul>
<li>BaudRate = 115200 baud</li>
<li>Word Length = 8 Bits</li>
<li>Stop Bit = 1</li>
<li>Parity = None</li>
<li>Flow control = None</li>
</ul></li>
</ul>
<h3 id="how-to-use-it"><b>How to use it ?</b></h3>
<p>In order to make the program work, you must do the following :</p>
<ul>
<li><p>Open your preferred toolchain</p></li>
<li><p>Edit the file <code> NetXDuo/App/app_netxduo.h</code> and correctly define the <UDP_SERVER_ADDRESS> and <UDP_SERVER_PORT> to connect on.</p></li>
<li><p>run the <a href="https://github.com/PavelBansky/EchoTool/releases/tag/v1.5.0.0">echotool</a> utility on a windows console as following:</p>
<pre><code>c:\&gt; .\echotool.exe /p udp /s &lt;UDP_SERVER_PORT&gt; 

example : c:\&gt; .\echotool.exe /p udp /s 6001 </code></pre></li>
<li><p>Rebuild all files and load your image into target memory</p></li>
<li><p>Run the application</p></li>
</ul>
</section>
</div>
</body>
</html>
